package com.bestcem.xm.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.common.core.enums.ReqErrorCodeEnum;
import com.bestcem.xm.common.core.enums.ResourceErrorCodeEnum;
import com.bestcem.xm.component.security.context.SecurityContextHolder;
import com.bestcem.xm.user.constant.CommonConstant;
import com.bestcem.xm.user.dao.RolePermissionDao;
import com.bestcem.xm.user.entity.pojo.RolePermissionDO;
import com.bestcem.xm.user.service.RolePermissionService;
import com.bestcem.xm.user.service.RoleService;
import com.bestcem.xm.user.service.UserService;
import com.bestcem.xm.user.service.dto.role.RolePermissionDTO;
import com.bestcem.xm.user.util.business.DataBaseUtil;
import com.bestcem.xm.user.util.business.UserPermissionUtil;
import com.bestcem.xm.user.util.convert.RolePermissionConvert;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

/**
 * 用户权限
 *
 * @author Linked <zhijian.lin@idiaoyan.com>
 * @version v1.0
 * @date 2022/3/8 18:41
 */
@Slf4j
@Service
public class RolePermissionServiceImpl implements RolePermissionService {

    @Resource
    private UserService userService;

    @Resource
    private
    RoleService roleService;

    @Resource
    private RolePermissionConvert rolePermissionConvert;

    @Resource
    private RolePermissionDao rolePermissionDao;

    @Resource
    private UserPermissionUtil permissionUtil;


    @Override
    public Boolean hasPermission(String orgId, String userId, String method, String url) {
        if (StringUtils.isAnyEmpty(userId, method, url)) {
            return false;
        }
        // 获取userId对应的用户权限列表
        ServiceResult<List<String>> permissionResult = userService.getUserPermissionList(orgId, userId);
        if (!permissionResult.isSuccess() || CollectionUtils.isEmpty(permissionResult.getData())) {
            return false;
        }
        // {"ACTION_ACTION": ["ACTION.ENTRY"],"PROJECT_PROJECT": ["EDIT.ENTRY"],"PROJECT_DATAREPORT": []}
        List<String> permissionList = permissionResult.getData();
        // 如果包含所有权限则返回True
        if (permissionList.contains(CommonConstant.ALL_PERMISSION)) {
            return true;
        }
        Set<String> userPermSet = new HashSet<>();
        List<JSONObject> permissionObjectList = new ArrayList<>();
        for (String permission : permissionList) {
            permissionObjectList.add(JSON.parseObject(permission));
        }
        // userPermSet 包含用户实际拥有哪些权限 {"LIB_COMMON": [], "LIB_TEMPLATE": []}
        for (JSONObject permissionObject : permissionObjectList) {
            for (Map.Entry<String, Object> permMap : permissionObject.entrySet()) {
                String res = permMap.getKey();
                List<String> ops = JSON.parseArray(permMap.getValue().toString(), String.class);
                for (String op : ops) {

                    // "PROJECT_QDES.SETTING.ENTRY"
                    // "ANALYSIS_DASHBOARD.DASHBOARD.SHARE"
                    // "USER_ORGANIZATION.ACCOUNT.VIEW"
                    // "USER_ORGANIZATION.ACCOUNT.EDIT"
                    userPermSet.add(String.format("%s.%s", res, op));
                }
            }
        }


        // 获取请求url和method对应的权限列表
        Set<String> handlerPremSet = permissionUtil.getHandlerPermissions(method, url);
        userPermSet.retainAll(handlerPremSet);
        return !CollectionUtils.isEmpty(userPermSet);
    }

    @Override
    public ServiceResult<String> insertSelective(RolePermissionDTO rolePermissionDTO) {
        if (Objects.isNull(rolePermissionDTO)) {
            return ServiceResult.fail(ReqErrorCodeEnum.PARAM_LOST, "参数不能为空");
        }
        // 保存角色的权限
        String rolePermissionId = rolePermissionDao.insertSelective(rolePermissionConvert.dto2Do(rolePermissionDTO));
        rolePermissionDTO.setRolePermissionId(rolePermissionId);
        // 设置返回值
        return ServiceResult.success(rolePermissionId);
    }

    @Override
    public ServiceResult<Integer> updateByPrimaryKeySelective(RolePermissionDTO rolePermissionDTO) {
        Integer result = rolePermissionDao.updateByPrimaryKeySelective(rolePermissionConvert.dto2Do(rolePermissionDTO));
        if (result > 0) {
            return ServiceResult.success(result);
        }
        return ServiceResult.fail("更新失败");
    }

    @Override
    public ServiceResult<Integer> deleteRolePermissionByRoleId(String roleId) {
        Integer result = rolePermissionDao.deleteRolePermissionByRoleId(roleId);
        if (result > 0) {
            return ServiceResult.success(result);
        }
        return ServiceResult.fail("删除失败");
    }

    @Override
    public ServiceResult<RolePermissionDTO> selectByOrgIdAndRoleId(String orgId, String roleId) {
        // 校验参数
        if (StringUtils.isBlank(orgId) || StringUtils.isBlank(roleId)) {
            return ServiceResult.fail("参数为空");
        }
        // 查询并返回结果
        RolePermissionDO rolePermissionDO = rolePermissionDao.selectByOrgIdAndRoleId(orgId, roleId);
        return ServiceResult.success(rolePermissionConvert.do2Dto(rolePermissionDO));
    }

    @Override
    public ServiceResult<List<RolePermissionDTO>> listByRoleIds(List<String> roleIds, String orgId) {
        // 校验参数
        if (CollectionUtils.isEmpty(roleIds) || StringUtils.isBlank(orgId)) {
            return ServiceResult.fail("参数为空");
        }
        // 查询并返回结果
        return ServiceResult.success(rolePermissionConvert.dos2Dtos(rolePermissionDao.listByRoleIds(roleIds, orgId)));
    }

    @Override
    public ServiceResult<Integer> updateByIds(List<String> roleIds, RolePermissionDTO rolePermissionDTO) {
        Integer rt = rolePermissionDao.updateByIds(roleIds, rolePermissionConvert.dto2Do(rolePermissionDTO));
        return ServiceResult.success(rt);
    }

    @Override
    public ServiceResult<Void> updateUserRolePermissions(String roleId, JSONObject permission) {
        String orgId = SecurityContextHolder.getToken().getOrgId();
        ServiceResult<String> result = roleService.getAdminRole(orgId);
        String adminRoleId = result.getData();
        ServiceResult<String> seniorAdminRole = roleService.getSeniorAdminRole(orgId);
        String seniorId = seniorAdminRole.getData();
        if (roleId.equals(adminRoleId) || roleId.equals(seniorId)) {
            ServiceResult.fail(ResourceErrorCodeEnum.UPDATE_FORBID, "cannot update super role");
        }
        String userId = SecurityContextHolder.getToken().getUserId();
        Date now = DataBaseUtil.getDate();
        ServiceResult<RolePermissionDTO> permissionResult = selectByOrgIdAndRoleId(orgId, roleId);
        RolePermissionDTO rolePermission = permissionResult.getData();
        if (Objects.isNull(rolePermission)) {
            // 保存权限
            RolePermissionDTO permissionDTO = new RolePermissionDTO();
            permissionDTO.setRoleId(roleId);
            permissionDTO.setOrgId(orgId);
            permissionDTO.setPermission(permission.toJSONString());
            permissionDTO.setCreatorId(userId);
            permissionDTO.setOperatorId(userId);
            permissionDTO.setCreateTime(now);
            permissionDTO.setUpdateTime(now);
            insertSelective(permissionDTO);
        } else {
            // 更新权限
            RolePermissionDTO rolePermissionDTO = new RolePermissionDTO();
            rolePermissionDTO.setRolePermissionId(rolePermission.getRolePermissionId());
            rolePermissionDTO.setPermission(permission.toJSONString());
            rolePermissionDTO.setUpdateTime(DataBaseUtil.getDate());
            rolePermissionDTO.setOperatorId(userId);
            updateByPrimaryKeySelective(rolePermissionDTO);
        }
        return ServiceResult.success();
    }

}
